#include "hrd_core.h"
#include "hrd_table.h"
#include "hrd_coord.h"
#include "hrd_bitmask.h"

static inline void convertCoordinateIntoTableIndexs(struct coordinate_s coordinate, uint8_t *pointer_to_i, uint8_t  *pointer_to_j)
{
    *pointer_to_i = 7 - coordinate.y;
    *pointer_to_j = coordinate.x;
}


static hrd_bitmask_t calculateDisplayBoundary(hrd_problem_t *hrd_problem)
{
    hrd_bitmask_t display_boundary;

    display_boundary = HrdBitmask_GetBoundary(hrd_problem->bitmask_list);
    display_boundary &= ~HrdBitmask_GenerateNewObjectBitmask(hrd_problem->goal, MOVE_UP, 1);
    display_boundary &= ~HrdBitmask_GenerateNewObjectBitmask(hrd_problem->goal, MOVE_DOWN, 1);
    display_boundary &= ~HrdBitmask_GenerateNewObjectBitmask(hrd_problem->goal, MOVE_LEFT, 1);
    display_boundary &= ~HrdBitmask_GenerateNewObjectBitmask(hrd_problem->goal, MOVE_RIGHT, 1);

    return display_boundary;
}


static void parseBoundary(hrd_problem_t *hrd_problem, int8_t table[8][8])
{
    uint8_t index;
    uint8_t i, j;
    hrd_bitmask_t display_boundary = calculateDisplayBoundary(hrd_problem);
    uint8_t coordinate_number;
    struct coordinate_s coordinate_list[MAX_COORDINATE_NUMBER];

    coordinate_number = HrdCoord_BitmaskToCoordinateList(display_boundary, coordinate_list);
    for (index = 0; index < coordinate_number; index++) {
        convertCoordinateIntoTableIndexs(
            coordinate_list[index],
            &i, &j
        );
        table[i][j] = BOUNDARY_CODE;
    }
}


static void parseObjects(hrd_problem_t *hrd_problem, int8_t table[8][8])
{
    uint8_t coord_index, object_index;
    uint8_t i, j;
    uint8_t coordinate_number;
    struct coordinate_s coordinate_list[MAX_COORDINATE_NUMBER];

    for (object_index = 1; object_index < hrd_problem->object_number + 1; object_index++) {
        coordinate_number = HrdCoord_BitmaskToCoordinateList(
            hrd_problem->bitmask_list[object_index], coordinate_list
        );

        for (coord_index = 0; coord_index < coordinate_number; coord_index++) {
            convertCoordinateIntoTableIndexs(
                coordinate_list[coord_index],
                &i, &j
            );
            table[i][j] = object_index;
        }
    }
}


static void parseEmptySpace(int8_t table[8][8])
{
    int i, j;
    for (i = 0; i < 8; i++) {
        for (j = 0; j < 8; j++) {
            table[i][j] = EMPTY_SPACE_CODE;
        }
    }
}


void HrdTable_ParseProblemToTable(hrd_problem_t *hrd_problem, int8_t table[8][8])
{
    parseEmptySpace(table);
    parseBoundary(hrd_problem, table);
    parseObjects(hrd_problem, table);
}